#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include  <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>

#define TYPECAST_TA_PORT 2048

static void receive_packet(int port); 
static void send_packet(int port); 

main(int argc, char ** argv) 
{
	
	int port = atoi(argv[2]); 
	if (strcmp(argv[1], "-client") == 0) { 
		send_packet(port); 
	} else { 
		receive_packet(port); 	
	}		
}

static void receive_packet(int port) 
{ 
	struct sockaddr_in src_addr; 
	socklen_t addrlen = sizeof(src_addr); 
	char buf[1248]; 
	
	    // Initialize socket
    int receive_sock_fd = socket(PF_INET, SOCK_DGRAM, 0); 
    if (receive_sock_fd < 0)
    { 
        perror("Error creating receiving socket.\n"); 
        exit(-1); 
    }

    const int on = 1; 
    if (setsockopt(receive_sock_fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
    {
        perror("Error when setsockopt in ConstructReceiveSockets\n");
        exit(-1);
    }

    // Bind the server.
    struct sockaddr_in serverName = { 0 };
    serverName.sin_family = AF_INET;
    serverName.sin_addr.s_addr = htonl(INADDR_ANY);
    serverName.sin_port = htons(port);

    if (bind(receive_sock_fd, (struct sockaddr *) &serverName, sizeof(serverName)) < 0)
    { 
        perror("bind()\n");
        exit(-1); 
    }

    int msglen; 
    
    while(1) {     	
	    msglen =  recvfrom(receive_sock_fd, buf,  sizeof(buf), 0, &src_addr, &addrlen);
	    if (msglen < 0) { 
	      perror("Error when recvfrom"); 
	      continue; 
	    }
	    
	    printf("Received packet from %s: length is %d\n", inet_ntoa(src_addr.sin_addr) , (int)msglen ); 
    }
    	
}
static void send_packet(int port) 
{ 
	char buf[1024]; 
	int packet_size = 1024; 
	int send_sock_fd; 

	
    send_sock_fd = socket(PF_INET, SOCK_DGRAM, 0); 
    if (send_sock_fd < 0)
    { 
        perror("Error creating sending socket.\n"); 
        exit(-1); 
    }

    const int on = 1; 
    if (setsockopt(send_sock_fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
    {
        perror("Error in setsockopt in ConstructSendSockets.\n"); 
        exit(-1); 
    }

	    // Set up broadcast destination
    struct sockaddr_in dst_addr; 
    memset(&dst_addr, 0, sizeof(dst_addr));
    dst_addr.sin_family = AF_INET; 
    dst_addr.sin_addr.s_addr = htonl(inet_addr("255.255.255.255")); 
    dst_addr.sin_port = htons(port); 

    ssize_t msglen; 
    while(1) { 
    	printf("Sending %d bytes to  address %s\n", packet_size,  "255.255.255.255");         	
	    msglen = sendto(send_sock_fd, buf, packet_size, 0, (struct sockaddr *) &dst_addr, sizeof(dst_addr) );
	    if (msglen < 0) 
	    { 
	        perror("Error when sendto.\n"); 
	        exit(-1); // Too bad if it fails.
	    }
	    sleep(5); 
    }
}